package com.kaibes.web.response;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.kaibes.core.base.util.StringUtils;

@RestControllerAdvice
public class ResponseStatusAdvice implements ResponseBodyAdvice<LinkedHashMap<String, Object>> {

    @Value("${kaibes.web.response.remove-trace:true}")
    private boolean removeTrace;
    @Autowired
    private ResponseConfig statusConfig;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if (returnType.getMethod().getName().equals("error")
                && converterType == MappingJackson2HttpMessageConverter.class) {
            return true;
        }
        return false;
    }
    
    private static String urlEncode(String message) {
        try {
            return URLEncoder.encode(message, "utf-8");
        } catch (UnsupportedEncodingException e) {
            return message;
        }
    }

    @Override
    public LinkedHashMap<String, Object> beforeBodyWrite(LinkedHashMap<String, Object> body, MethodParameter returnType,
            MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
            ServerHttpRequest request, ServerHttpResponse response) {
    	
        if (removeTrace && body.containsKey("trace")) {
            body.remove("trace");
        }
        
        if (body.containsKey("status")) {
            int status = (int) body.get("status");
            StatusBody statusBody = statusConfig.getStatusBodyMap().get(status);
            if (statusBody != null) {
            	boolean flag = response.getHeaders().containsKey(ResponseFactory.MESSAGE);
                if (!flag && StringUtils.isNotBlank(statusBody.getMessage())) {
                    String message = statusBody.getMessage();
                    response.getHeaders().add(ResponseFactory.MESSAGE, urlEncode(message));
                    if (body.containsKey("message")) {
                        String temp = (String) body.get("message");
                        temp = String.format(temp, body.get("path"), request.getMethod());
                        if (StringUtils.isBlank(temp)) {
                            body.put("message", message);
                        }
                    }
                }
                if (StringUtils.isNotBlank(statusBody.getRedirect())) {
                    response.getHeaders().add(ResponseFactory.REDIRECT, statusBody.getRedirect());
                    body.put("redirect", statusBody.getRedirect());
                }
            }
            body.put("method", request.getMethod());
        }
        return body;
    }

}
